//
//  YZChatVC.m
//  CocoaAsyncSocketClient
//
//  Created by lixiaoyi on 2018/6/20.
//  Copyright © 2018年 lixiaoyi. All rights reserved.
//

#import "YZChatVC.h"
#import "ChatHeader.h"
#import "YZChatCell.h"
#import "YZMessageModel.h"
#import "ClientSocket.h"
#import "ImMessage.pbobjc.h"
#import "varint.h"
#import "ChatKeyBoard.h"
#import "NSString+LZBTranscoding.h"
#import "YZRecordManager.h"
#import "YZMessageHelper.h"
#import "YZMessageFrame.h"
#import "YZChatMessageBaseCell.h"
#import "YZChatMessageTextCell.h"
#import "YZChatMessageVoiceCell.h"
#import "YZChatMessageImageCell.h"
#import "YZChatMessageVideoCell.h"
#import "YZChatMessageSystemCell.h"
#import "YZMessageHelper.h"
#import "YZMessageConst.h"
#import "UIImage+YZExtension.h"
#import "YZMediaManager.h"
#import "YZFileTool.h"
#import "YZPhotoBrower.h"
#import "YZVideoManager.h"
#import "NSString+YZExtension.h"
#import "YZImageManager.h"
#import "YZVideoView.h"
#import <AVKit/AVKit.h>
#import "YZVoiceHud.h"
#import "YZDBManager.h"
#import "YZChatUtils.h"
#import "YZChatPeer.h"
#import "YZMessageListModel.h"
#import "YZUser.h"
#import "YZFriendVM.h"
#import "YZNetworkConfig.h"

#define INIT_INPUT
#define HEART_TIME 5


@interface YZChatVC ()<UITableViewDelegate,UITableViewDataSource,
            UITextFieldDelegate,ClientSocketDelegate,ChatKeyBoardDelegate, ChatKeyBoardDataSource,BaseCellDelegate,YZRecordManagerDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UIViewControllerTransitioningDelegate,UIViewControllerAnimatedTransitioning>
{
    CGRect _smallRect;
    CGRect _bigRect;
    
    UIMenuItem * _copyMenuItem;
    UIMenuItem * _deleteMenuItem;
    UIMenuItem * _forwardMenuItem;
    UIMenuItem * _recallMenuItem;
    NSIndexPath *_longIndexPath;
    
    BOOL   _isKeyBoardAppear;     // 键盘是否弹出来了
}
@property (nonatomic, strong) UITableView *chatTable;
@property (nonatomic, strong) NSMutableArray *chatData;
@property (nonatomic, strong) UITapGestureRecognizer *tapGes;

@property (nonatomic, strong) NSFileManager *fileMgr;
@property (nonatomic, copy) NSString *audioRecoderSavePath;
@property (nonatomic, copy) NSString *tempRecorderPath;
@property (nonatomic, copy) NSString *recorderName;
@property (nonatomic, strong) UIImageView *currentVoiceIcon;

@property (strong, nonatomic) UIImagePickerController *imagePicker;
@property (nonatomic, strong) UIImageView *presentImageView;
@property (nonatomic, assign)  BOOL presentFlag;  // 是否model出控制器

// 所有接收到的数据大小
@property (nonatomic) NSUInteger allSize;

// 所有接收到的数据
@property (nonatomic, strong) NSMutableData *allData;

// 待读字节
@property (nonatomic) unsigned long long bufferSize;

// 缓冲区
@property (nonatomic, strong) NSMutableData *buffer;

// 发送的消息
@property (nonatomic, strong) ImMessage *mess;

// 聊天键盘
@property (nonatomic, strong) ChatKeyBoard *chatKeyBoard;

// 录音文件名
@property (nonatomic, copy) NSString *recordName;

// 录制视频view
@property (nonatomic, strong) YZVideoView *videoView;

// 录音显示
@property (nonatomic, strong)YZVoiceHud *voiceHud;

// 语音动画
@property (nonatomic, strong) NSTimer *timer;

// 最后显示时间消息的时间
@property (nonatomic) int64_t lastVisibleTime;

// VM
@property (nonatomic, strong) YZFriendVM *friendVM;


@end

static BOOL isSendSuccess;


@implementation YZChatVC

#pragma mark - lifecycle
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.title = @"聊天";
    self.chatTable.tableFooterView = [UIView new];
    [self.view addSubview:self.chatTable];
    [self.view addGestureRecognizer:self.tapGes];
    self.navigationController.interactivePopGestureRecognizer.delaysTouchesBegan = NO;
    [self.view addSubview:self.chatKeyBoard];
    self.chatKeyBoard.associateTableView = self.chatTable;
    
    NSLog(@"sender--->%@,receiver--->%@",[YZChatPeer shared].sender,[YZChatPeer shared].receiver);
    
    // 注册cell
    [self registerCell];
    
    // 检查文件保存目录
    if (![self.fileMgr fileExistsAtPath:self.audioRecoderSavePath]) {
        NSError *error = nil;
        BOOL isCreateDir = [self.fileMgr createDirectoryAtPath:self.audioRecoderSavePath withIntermediateDirectories:YES attributes:nil error:&error];
        if (!isCreateDir) {
            NSLog(@"CreateDirError--->%@",error);
        }
    }
    
    // 待读字节数
    _bufferSize = 0;
    
    // 缓冲区
    _buffer = [NSMutableData data];
    
    // 消息是否发送成功
    isSendSuccess = NO;
    
    // 查询聊天记录
    self.chatData = [[YZDBManager sharedManage] queryDataFromTable:kChatRecordTable andCondition:[NSString stringWithFormat:@"sender = '%@' and receiver = '%@'",[YZChatPeer shared].sender,[YZChatPeer shared].receiver]];
    
    NSLog(@"self.chatData ---->%@",self.chatData);
    
    // 最后显示时间消息的时间
    if (![YZDBManager sharedManage].lastVisibleTime || [YZDBManager sharedManage].lastVisibleTime ==0) {
        [YZDBManager sharedManage].lastVisibleTime = [[YZChatUtils getTimeInterval2] longLongValue];
    }
    self.lastVisibleTime = [YZDBManager sharedManage].lastVisibleTime;
    
}

- (void)registerCell {
    [self.chatTable registerClass:[YZChatMessageTextCell class] forCellReuseIdentifier:TypeText];
    [self.chatTable registerClass:[YZChatMessageVoiceCell class] forCellReuseIdentifier:TypeVoice];
    [self.chatTable registerClass:[YZChatMessageImageCell class] forCellReuseIdentifier:TypePic];
    [self.chatTable registerClass:[YZChatMessageVideoCell class] forCellReuseIdentifier:TypeVideo];
    [self.chatTable registerClass:[YZChatMessageSystemCell class] forCellReuseIdentifier:TypeSystem];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // 显示导航栏
    [self.navigationController.navigationBar setHidden:NO];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    // 隐藏导航栏
    [self.navigationController.navigationBar setHidden:YES];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [ClientSocket shareSocket].socketHost = [YZNetworkConfig getImDomain][@"ip"];
    [ClientSocket shareSocket].socketPort = [[YZNetworkConfig getImDomain][@"port"] integerValue];
    [[ClientSocket shareSocket] autoConnection];
    [ClientSocket shareSocket].socketDelegate = self;
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [ClientSocket shareSocket].socketDelegate = nil;
    [[ClientSocket shareSocket] disConn];
    [ClientSocket attempDealloc];
}

#pragma mark - ClientSocketDelegate
- (void)clientSocket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    NSLog(@"建立连接成功");
    [[ClientSocket shareSocket].socket readDataWithTimeout:-1 tag:101];
    [ClientSocket shareSocket].connectd = YES;
    // 开启定时器
    if ([ClientSocket shareSocket].connectTimer) {
        [[ClientSocket shareSocket].connectTimer invalidate];
        [ClientSocket shareSocket].connectTimer = nil;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [[ClientSocket shareSocket] addTimer];
    });
}

- (void)clientSocket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    
    if (100 == tag) {
        // 心跳
    }
    else if (101 == tag) {
        // conn
        NSString *text = [YZChatUtils convertDataToHexStr:data];
        NSString *printText = [NSString stringWithFormat:@"服务器返回--->%@",text];
        NSLog(@"%@",printText);
        char *str = (char *)[data bytes];
        unsigned char bts;
        unsigned long long r = varint_decode(str, 7, &bts);
        
        int btsLen = (int)bts;
        // 反序列化
        NSMutableString *realStr = [NSMutableString string];
        if (r * 2 <= text.length - btsLen * 2) {
            NSString *tempStr = [text substringWithRange:NSMakeRange(btsLen * 2, r * 2)];
            realStr = [NSMutableString stringWithString:tempStr];
            
            NSData *realData = [YZChatUtils dataFormHexString:realStr];
            ImMessage *p = [ImMessage parseFromData:realData error:nil];
//            DLog(@"p>>>%@",p);
            
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
                
                // 刷新页面
                YZMessageFrame *messageF = [YZMessageHelper createMessageFrame:TypeText imMessage:self.mess path:nil fileKey:nil isSender:NO rececivedSenderbySelf:NO senderAvatar:@"" receiverAvatar:@""];
                
                [self refreshTableByMessageFrame:messageF];
                
                // 给服务器发送ack,确认收到离线消息
                [[ClientSocket shareSocket] doAck:p.messageId];
            };
        }
    } else {
        _allSize += data.length;
        [_allData appendData:data];
        NSLog(@"_allsize--->%ld",_allSize);
        [self readBytes:data];
    }
    
    
    // 继续接收数据
    [[ClientSocket shareSocket].socket readDataWithTimeout:-1 tag:0];
}

- (void)readBytes:(NSData *)data {
    // 过滤心跳包
    NSString *text = [YZChatUtils convertDataToHexStr:data];
    if ([self isDelayHeartRecData:text]) {
        NSLog(@"接收心跳OK");
        [ClientSocket shareSocket].receHearDt = [NSDate date];
        NSTimeInterval interlTimer = [[ClientSocket shareSocket].receHearDt timeIntervalSinceDate:[ClientSocket shareSocket].sendHeartDt];
        if (interlTimer < HEART_TIME * 2) {
            interlTimer = 0;
            return;
        } else {
            // 连接失效，客户端关闭socket并重新建立连接
            NSLog(@"心跳失效，重新连接");
            
            // 重新连接
            dispatch_async(dispatch_get_main_queue(), ^{
                [[ClientSocket shareSocket] autoConnection];
            });
        }
    }
    
    // 如果待读字节数大于0
    if (_bufferSize > 0) {
        if (data.length < _bufferSize) {
            // 继续读
            _bufferSize = _bufferSize - data.length;
            [_buffer appendData:data];
        } else {
            NSData *temp = [data subdataWithRange:NSMakeRange(0, _bufferSize)];
            [_buffer appendData:temp];
            // 解析数据
            ImMessage *p = [ImMessage parseFromData:_buffer error:nil];
            NSLog(@"p>>>%@",p);
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
                isSendSuccess = YES;
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
                
                // 正在聊天
                if([p.sender isEqualToString:[YZChatPeer shared].receiver] &&
                   [p.receiver isEqualToString:[YZChatPeer shared].sender]) {
                    // 刷新页面
                    [self accpetMessage:p];
                } else {
                    // 正在聊的时候收到别人发的消息
                    // 接收Model
                    NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                    YZMessageListModel *model = [YZMessageListModel new];
                    model.name = p.sender;
                    model.imageName = [YZChatPeer shared].receiverAvatar;
                    model.showUserId = p.sender;
                    model.message = recStr;
                    model.time = p.messageTime;
                    model.receiver = p.receiver;
                    model.showRedHot = YES;
                    
                    // 从数据库查询红点数量，没有查到就是0
                    model.redHotNumber = [self refreshRedHotNum:model];
                    NSLog(@"redHotNumber---------->%@",model.redHotNumber);
                    
                    // 发送更新消息列表通知
                    [[NSNotificationCenter defaultCenter] postNotificationName:RefreshMessaegListNotification object:model];
                }
            };
            
            // 剩余的再处理一次
            NSUInteger leftInt = data.length - _bufferSize;
            if (leftInt > 0) {
                NSData *leftData = [data subdataWithRange:NSMakeRange(_bufferSize, data.length - _bufferSize)];
                
                // 重置buffer
                _bufferSize = 0;
                _buffer = [NSMutableData data];
                
                [self readBytes:leftData];
            } else {
                // 重置buffer
                _bufferSize = 0;
                _buffer = [NSMutableData data];
            }
        }
    } else {
        char *str = (char *)[data bytes];
        unsigned char bts;
        unsigned long long r = varint_decode(str, 7, &bts);
        int btsLen = (int)bts;
        if (data.length < r + btsLen) {
            _bufferSize = r - data.length + btsLen;
            NSData *appData = [data subdataWithRange:NSMakeRange(btsLen, data.length - btsLen)];
            [_buffer appendData:appData];
        } else if (data.length == r + btsLen) {
            // 解析数据
            NSData *tempData = [data subdataWithRange:NSMakeRange(btsLen, r)];
            ImMessage *p = [ImMessage parseFromData:tempData error:nil];
            NSLog(@"p>>>%@",p);
            
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
                isSendSuccess = YES;
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
                
                // 正在聊天
                if([p.sender isEqualToString:[YZChatPeer shared].receiver] &&
                   [p.receiver isEqualToString:[YZChatPeer shared].sender]) {
                    // 刷新页面
                    [self accpetMessage:p];
                } else {
                    // 正在聊的时候收到别人发的消息
                    // 接收Model
                    NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                    YZMessageListModel *model = [YZMessageListModel new];
                    model.name = p.sender;
                    model.imageName = [YZChatPeer shared].receiverAvatar;
                    model.showUserId = p.sender;
                    model.message = recStr;
                    model.time = p.messageTime;
                    model.receiver = p.receiver;
                    model.showRedHot = YES;
                    
                    // 从数据库查询红点数量，没有查到就是0
                    model.redHotNumber = [self refreshRedHotNum:model];
                    NSLog(@"redHotNumber---------->%@",model.redHotNumber);
                    
                    // 发送更新消息列表通知
                    [[NSNotificationCenter defaultCenter] postNotificationName:RefreshMessaegListNotification object:model];
                }
            };
        } else if (data.length > r + btsLen) {
            // 粘包
            NSData *appData = [data subdataWithRange:NSMakeRange(r + btsLen + btsLen, data.length - r - btsLen - btsLen)];
            [_buffer appendData:appData];
            NSData *dealData = [data subdataWithRange:NSMakeRange(btsLen, r)];
            
            // 解析数据
            ImMessage *p = [ImMessage parseFromData:dealData error:nil];
            NSLog(@"p>>>%@",p);
            
            // 打印确认接收报文日志
            if ([p.messageType isEqualToString:@"ack"]) {
                NSLog(@"收到服务器确认");
                isSendSuccess = YES;
            } else if ([p.messageType isEqualToString:@"data"]) {
                NSLog(@"确认接收消息，发送ack消息");
                // 显示离线消息
                NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                NSString *showMsg = [NSString stringWithFormat:@"收到离线消息--->%@",recStr];
                NSLog(@"%@",showMsg);
                // 正在聊天
                if([p.sender isEqualToString:[YZChatPeer shared].receiver] &&
                   [p.receiver isEqualToString:[YZChatPeer shared].sender]) {
                    // 刷新页面
                    [self accpetMessage:p];
                } else {
                    // 正在聊的时候收到别人发的消息
                    // 接收Model
                    NSString *recStr = [[NSString alloc] initWithData:p.payload encoding:NSUTF8StringEncoding];
                    YZMessageListModel *model = [YZMessageListModel new];
                    model.name = p.sender;
                    model.imageName = [YZChatPeer shared].receiverAvatar;
                    model.showUserId = p.sender;
                    model.message = recStr;
                    model.time = p.messageTime;
                    model.receiver = p.receiver;
                    model.showRedHot = YES;
                    
                    // 从数据库查询红点数量，没有查到就是0
                    model.redHotNumber = [self refreshRedHotNum:model];
                    NSLog(@"redHotNumber---------->%@",model.redHotNumber);
                    
                    // 发送更新消息列表通知
                    [[NSNotificationCenter defaultCenter] postNotificationName:RefreshMessaegListNotification object:model];
                }
            };
            
            // 剩余的再处理一次
            NSUInteger leftInt = data.length - btsLen - r;
            if (leftInt > 0) {
                NSData *leftData = [data subdataWithRange:NSMakeRange(btsLen + r, data.length - btsLen - r)];
                
                // 重置buffer
                _bufferSize = 0;
                _buffer = [NSMutableData data];
                
                [self readBytes:leftData];
            } else {
                // 重置buffer
                _bufferSize = 0;
                _buffer = [NSMutableData data];
            }
        }
    }
}


#pragma mark - lazy load
- (NSTimer *)timer
{
    if (!_timer) {
        _timer =[NSTimer scheduledTimerWithTimeInterval:0.3f target:self selector:@selector(progressChange) userInfo:nil repeats:YES];
    }
    return _timer;
}

- (void)timerInvalue
{
    [_timer invalidate];
    _timer  = nil;
}

- (YZVoiceHud *)voiceHud{
    if (!_voiceHud) {
        _voiceHud = [[YZVoiceHud alloc] initWithFrame:CGRectMake(0, 0, 155, 155)];
        _voiceHud.hidden = YES;
        [self.view addSubview:_voiceHud];
        _voiceHud.center = CGPointMake(kWidth/2, kHeight/2);
    }
    return _voiceHud;
}

- (YZVideoView *)videoView {
    if (!_videoView) {
       _videoView = [[YZVideoView alloc] initWithFrame:CGRectMake(0, kHeight - videwViewH, kWidth, videwViewH)];
    }
    
    return _videoView;
}

- (UIImageView *)presentImageView
{
    if (!_presentImageView) {
        _presentImageView = [[UIImageView alloc] init];
    }
    return _presentImageView;
}

- (UIImagePickerController *)imagePicker {
    if (!_imagePicker) {
        _imagePicker = [[UIImagePickerController alloc] init];
        _imagePicker.delegate = self;
        _imagePicker.allowsEditing = YES;
    }
    
    return _imagePicker;
}

- (NSFileManager *)fileMgr {
    if (!_fileMgr) {
        _fileMgr = [NSFileManager defaultManager];
    }
    
    return _fileMgr;
}

- (NSString *)audioRecoderSavePath {
    if (!_audioRecoderSavePath) {
        NSDate *date = [NSDate date];
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        [formatter setDateFormat:@"YYYY-MM-dd"];
        NSString *dateFolder = [formatter stringFromDate:date];
        NSString *dateAudioPath = [NSString stringWithFormat:@"%@/",dateFolder];
        // 文件目录
//        NSLog(@"homeDic--->%@",NSHomeDirectory());
//        NSString *documentDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
        
        NSString *cacheAudioPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        _audioRecoderSavePath = [NSString stringWithFormat:@"%@/%@",cacheAudioPath,dateAudioPath];
    }
    
    return _audioRecoderSavePath;
}

- (ChatKeyBoard *)chatKeyBoard {
    if (!_chatKeyBoard) {
        _chatKeyBoard = [ChatKeyBoard keyBoardWithNavgationBarTranslucent:YES];
        _chatKeyBoard.delegate = self;
        _chatKeyBoard.dataSource = self;
    }
    
    return _chatKeyBoard;
}

- (UITableView *)chatTable {
    if (!_chatTable) {
        CGRect tableFrame = CGRectMake(0, 0, kWidth, kHeight - 49 );
        _chatTable  = [[UITableView alloc] initWithFrame:tableFrame style:UITableViewStylePlain];
        _chatTable.delegate = self;
        _chatTable.dataSource = self;
        _chatTable.showsVerticalScrollIndicator = NO;
        _chatTable.separatorStyle = UITableViewCellSeparatorStyleNone;
    }
    
    return _chatTable;
}

- (NSMutableArray *)chatData {
    if (!_chatData) {
        _chatData = [NSMutableArray array];
    }
    
    return _chatData;
}

- (UITapGestureRecognizer *)tapGes {
    if (!_tapGes) {
        _tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesClick:)];
    }
    
    return _tapGes;
}

- (YZFriendVM *)friendVM {
    if (!_friendVM) {
        _friendVM = [YZFriendVM new];
    }
    
    return _friendVM;
}

#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
    NSLog(@"从相册选择图片");
    UIImage *sendImage = [info valueForKey:@"UIImagePickerControllerOriginalImage"];
    NSData *sendImageData = UIImageJPEGRepresentation(sendImage, 0.5);
    // 保存图片
    UIImage *simpleImage = [UIImage simpleImage:sendImage];
    NSString *filePath = [[YZMediaManager shareManager] saveImage:simpleImage];
    
    
    // 异步发送图片
    dispatch_queue_t que = dispatch_queue_create("send_png_yinzi", DISPATCH_QUEUE_SERIAL);
    dispatch_async(que, ^{
        // 超过3分钟显示
        int64_t timeInterval = [[YZChatUtils getTimeInterval2] integerValue];
        if (timeInterval - self.lastVisibleTime > 60 * 3 * 1000) {
            // 发送时间
            [self sendMessageTime:timeInterval];
            self.lastVisibleTime = timeInterval;
        }
        
        
        // 创建消息体
        ImMessage *mess = [YZChatUtils createMessage:@"YZIMP"
                                      version:@"1.0"
                                       userId:[YZChatPeer shared].sender
                                    userToken:[YZUser sharedInstance].token
                                    messageId:1 messageType:@"data"
                                  messageTime:timeInterval
                                     termType:@"iOS"
                                     receiver:[YZChatPeer shared].receiver
                                       sender:[YZChatPeer shared].sender
                                ctrlMessageId:0
                                    mediaType:@"image/*"
                                     playload:sendImageData];
        
        
        
        // 创建消息对象
        YZMessageFrame *messageF = [YZMessageHelper createMessageFrame:TypePic imMessage:mess path:filePath fileKey:nil isSender:YES rececivedSenderbySelf:NO senderAvatar:[YZUser sharedInstance].avatar receiverAvatar:[YZChatPeer shared].receiverAvatar];
        [self.chatData addObject:messageF];
        
        // 开启新线程检查发送状态
        NSThread *newThread = [[NSThread alloc]initWithTarget:self selector:@selector(threadRun:) object:(@{@"type":@"image/*",@"msg":messageF,@"dt":sendImageData})];
        newThread.name = @"thread_check_send";
        [newThread start];
        
    });
    
    // 销毁
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    NSLog(@"取消了选择图片");
    [self dismissViewControllerAnimated:picker completion:nil];
}

#pragma mark - UIViewControllerTransitioningDelegate
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    self.presentFlag = YES;
    return self;
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    self.presentFlag = NO;
    return self;
}


#pragma mark - UIViewControllerAnimatedTransitioning
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext {
    return 0.5;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    if (self.presentFlag) {
        UIView *toView              = [transitionContext viewForKey:UITransitionContextToViewKey];
        self.presentImageView.frame = _smallRect;
        [[transitionContext containerView] addSubview:self.presentImageView];
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            self.presentImageView.frame = self->_bigRect;
        } completion:^(BOOL finished) {
            if (finished) {
                [self.presentImageView removeFromSuperview];
                [[transitionContext containerView] addSubview:toView];
                [transitionContext completeTransition:YES];
            }
        }];
    } else {
        YZPhotoBrower *photoVC = (YZPhotoBrower *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIImageView *iv     = photoVC.imageView;
        UIView *fromView    = [transitionContext viewForKey:UITransitionContextFromViewKey];
        iv.center = fromView.center;
        [fromView removeFromSuperview];
        [[transitionContext containerView] addSubview:iv];
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            iv.frame = self->_smallRect;
        } completion:^(BOOL finished) {
            if (finished) {
                [iv removeFromSuperview];
                [transitionContext completeTransition:YES];
            }
        }];
    }
}

#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.chatData count];;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    id obj = [self.chatData objectAtIndex:indexPath.row];
    if ([obj isKindOfClass:[NSString class]]) {
        return nil;
    } else {
        YZMessageFrame *modelFrame     = (YZMessageFrame *)obj;
        NSString *ID                   = modelFrame.model.message.type;
        NSLog(@"ID------------>%@",ID);
        if ([ID isEqualToString:TypeSystem]) {
            YZChatMessageSystemCell *cell = [YZChatMessageSystemCell cellWithTableView:tableView reusabled:ID];
            cell.messageF              = modelFrame;
            cell.timeLabel.text = modelFrame.model.message.content;
            CGSize newSize = [cell.timeLabel sizeThatFits:CGSizeZero];
            cell.timeLabel.frame = CGRectMake(kWidth/2-newSize.width/2, 0, newSize.width + 10, newSize.height + 5);
            return cell;
        }
        YZChatMessageBaseCell *cell    = [tableView dequeueReusableCellWithIdentifier:ID];
        cell.longPressDelegate         = self;
//        [[MediaManager sharedManager] clearReuseImageMessage:cell.modelFrame.model];
        cell.modelFrame                = modelFrame;
        
        
        // if cell is video cell
        if ([ID isEqualToString:TypeVideo]) {
            ((YZChatMessageVideoCell *)cell).videoPlayBlock = ^(NSString *videoFilePath) {
                NSString *cacheVideoPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
                cacheVideoPath = [cacheVideoPath stringByAppendingPathComponent:kChatVideoPath];
                videoFilePath = [cacheVideoPath stringByAppendingPathComponent:[videoFilePath lastPathComponent]];
                [[YZVideoManager shareManager] playVideo:videoFilePath parentVC:self];
            };
        }
        
        return cell;
    }
    
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    YZMessageFrame *messageF = [self.chatData objectAtIndex:indexPath.row];
    return messageF.cellHight;
}

#pragma mark - 查询用户信息
- (void)queryUserInfo:(YZMessage *)p {
    @weakify(self)
    [[self.friendVM queryUserInfo:p.receiver] subscribeNext:^(id  _Nullable x) {
        NSLog(@"查询用户信息------>%@",x);
        @try {
            NSString *recStr = @"";
            if ([p.mediaType isEqualToString:@"image/*"]) {
                recStr = @"[图片]";
            } else if ([p.mediaType isEqualToString:@"text/plain"]) {
                recStr = [[NSString alloc] initWithData:p.playLoad encoding:NSUTF8StringEncoding];
            } else if ([p.mediaType isEqualToString:@"audio/aac"]) {
                recStr = @"[语音]";
            } else if ([p.mediaType isEqualToString:@"video/mp4"]) {
                recStr = @"[视频]";
            }
            
            YZMessageListModel *model = [YZMessageListModel new];
            model.name = x[@"nickname"] ? : @"";
            model.imageName = x[@"avatar"] ? : @"";
            // showUserId这里指接收方
            model.showUserId = p.receiver;
            model.message = recStr;
            model.time = p.messageTime;
            // 这里作为发送方，要反着写(看Model定义，receiver是当前用户)
            model.receiver = p.sender;
            
            // 查询消息列表有没有和接收者的记录
            NSString *condStr = [NSString stringWithFormat:@"showUserid = '%@' and receiver = '%@'",model.showUserId,model.receiver];
            NSArray *resuts = [[YZDBManager sharedManage] queryDataFromTable:kChatMessageListTable andCondition:condStr];
            if (resuts.count == 0) {
                // 没有则插入
                BOOL insertRet = [[YZDBManager sharedManage] insertMessageListData:model tableName:kChatMessageListTable];
                if (insertRet) {
                    NSLog(@"插入消息列表成功");
                }
                
            } else {
                NSString *setStr = [NSString stringWithFormat:@"lastContent = '%@'",model.message];
                NSString *condition = [NSString stringWithFormat:@"showUserid = '%@'",model.showUserId];
                
                BOOL updateRet = [[YZDBManager sharedManage] updateData:setStr table:kChatMessageListTable andCondition:condition];
                if (updateRet) {
                    NSLog(@"更新消息列表成功");
                };
            }
        } @catch(NSException *exception) {
            
        }
    } completed:^{
        @strongify(self)
    }];
}

#pragma mark - 发送消息核心方法
- (void)doSendMessage:(NSData *)dMessage
            mediaType:(NSString *)mediaType
          messageType:(NSString *)messType{
    
    // 消息
    ImMessage *_mess = [YZChatUtils createMessage:@"YZIMP"
                                   version:@"1.0"
                                    userId:[YZChatPeer shared].sender
                                 userToken:[YZUser sharedInstance].token
                                 messageId:1
                               messageType:messType
                               messageTime:[[YZChatUtils getTimeInterval2] integerValue] termType:@"iOS"
                                  receiver:[YZChatPeer shared].receiver
                                    sender:[YZChatPeer shared].sender
                             ctrlMessageId:0
                                 mediaType:mediaType
                                  playload:dMessage
                                    avatar:@""
                        ];
    
    // 序列化
    NSData *allData = [_mess data];
    
    // 消息长度
    unsigned long long number = [allData length];
    char* str = calloc(7, sizeof(char));
    unsigned char bts;
    varint_encode(number, str, 7, &bts);
    NSData *headVarint = [NSData dataWithBytes:str length:bts];
    NSLog(@"headVarint>>>%@",headVarint);
    free(str);
    
    // 总个消息
    NSMutableData *totalData = [NSMutableData dataWithData:headVarint];
    [totalData appendData:allData];
    
    [[ClientSocket shareSocket].socket writeData:totalData withTimeout:-1 tag:0];
    
}

- (void)tapGesClick:(UITapGestureRecognizer *)reg{
    [self.view endEditing:YES];
}

#pragma mark - 刷新表格

- (void)refreshTableByMessageFrame:(YZMessageFrame *)messageF {
    [self.chatData addObject:messageF];
    // 刷新
    dispatch_async(dispatch_get_main_queue(), ^{
        // 修改消息发送为已发送
        messageF.model.message.deliveryState = ICMessageDeliveryState_Delivered;
        [self.chatTable reloadData];
        
        // 滑到最后一行
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.chatData.count - 1 inSection:0];
        [self.chatTable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    });
}

- (void)messageSendSuccess:(YZMessageFrame *)messageF {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 修改消息发送为已发送
        messageF.model.message.deliveryState = ICMessageDeliveryState_Delivered;
        [self.chatTable reloadData];
        
        // 滑到最后一行
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.chatData.count - 1 inSection:0];
        [self.chatTable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    });
}

- (void)messageSendFailure:(YZMessageFrame *)messageF {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 修改消息发送为发送失败
        messageF.model.message.deliveryState = ICMessageDeliveryState_Failure;
        [self.chatTable reloadData];
        
        // 滑到最后一行
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.chatData.count - 1 inSection:0];
        [self.chatTable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    });
}

#pragma mark - public method

// 路由响应
- (void)routerEventWithName:(NSString *)eventName
                   userInfo:(NSDictionary *)userInfo
{
    YZMessageFrame *modelFrame = [userInfo objectForKey:MessageKey];
    if ([eventName isEqualToString:GXRouterEventTextUrlTapEventName]) {
    } else if ([eventName isEqualToString:GXRouterEventImageTapEventName]) {
        // 先关闭键盘
        [_chatKeyBoard keyboardDown];
        _smallRect             = [[userInfo objectForKey:@"smallRect"] CGRectValue];
        _bigRect               =  [[userInfo objectForKey:@"bigRect"] CGRectValue];
        NSString *imgPath      = modelFrame.model.mediaPath;
        NSString *orgImgPath = [[YZMediaManager shareManager] originImgPath1:modelFrame];
        if ([YZFileTool fileExistsAtPath:orgImgPath]) {
            modelFrame.model.mediaPath = orgImgPath;
            imgPath                    = orgImgPath;
        }
        [self showLargeImageWithPath:imgPath withMessageF:modelFrame];
    } else if ([eventName isEqualToString:GXRouterEventVoiceTapEventName]) {
        
        UIImageView *imageView = (UIImageView *)userInfo[VoiceIcon];
        UIView *redView        = (UIView *)userInfo[RedView];
        [self chatVoiceTaped:modelFrame voiceIcon:imageView redView:redView];
    } if ([eventName isEqualToString:GXRouterEventVideoRecordExit]) {
        [self resignFirstResponder];
        [self.videoView removeFromSuperview];
        self.videoView = nil;
    } else if ([eventName isEqualToString:GXRouterEventVideoRecordFinish]) {
        // 移除录制视频view
        [self resignFirstResponder];
        [self.videoView removeFromSuperview];
        self.videoView = nil;
        [[YZVideoManager shareManager] exit];
        
        
        // 发送视频
        NSLog(@"准备发送视频");
        NSString *finish = userInfo[@"VideoPathKey"];
        NSData *sendVideoData = [YZChatUtils dataFromPath:finish];
        dispatch_queue_t que = dispatch_queue_create("send_video_yinzi", DISPATCH_QUEUE_SERIAL);
        dispatch_async(que, ^{
            
            int64_t timeInterval = [[YZChatUtils getTimeInterval2] integerValue];
            if (timeInterval - self.lastVisibleTime > 60 * 3 * 1000) {
                // 发送时间
                [self sendMessageTime:timeInterval];
                self.lastVisibleTime = timeInterval;
            }
            
            // 创建消息体
            ImMessage *mess = [YZChatUtils createMessage:@"YZIMP"
                                          version:@"1.0"
                                           userId:[YZChatPeer shared].sender
                                        userToken:[YZUser sharedInstance].token
                                        messageId:1 messageType:@"data"
                                      messageTime:timeInterval
                                         termType:@"iOS"
                                         receiver:[YZChatPeer shared].receiver
                                           sender:[YZChatPeer shared].sender
                                    ctrlMessageId:0
                                        mediaType:@"video/mp4"
                                         playload:sendVideoData];
            
            
            
            // 创建消息对象
            YZMessageFrame *messageF = [YZMessageHelper createMessageFrame:TypeVideo imMessage:mess path:finish fileKey:nil isSender:YES rececivedSenderbySelf:NO senderAvatar:[YZUser sharedInstance].avatar receiverAvatar:[YZChatPeer shared].receiverAvatar];
            [self.chatData addObject:messageF];
            
            // 开启新线程检查发送状态
            NSThread *newThread = [[NSThread alloc]initWithTarget:self selector:@selector(threadRun:) object:(@{@"type":@"video/mp4",@"msg":messageF,@"dt":sendVideoData})];
            newThread.name = @"thread_check_send";
            [newThread start];
        });
    }
}

#pragma mark - private
// 更新model小红点数量
- (NSNumber *)refreshRedHotNum:(YZMessageListModel *)model {
    // 从数据库查询红点数量，没有查到就是0
    NSString *condition = [NSString stringWithFormat:@"showUserid = '%@'",model.showUserId];
    NSArray *dotArr = [[YZDBManager sharedManage] queryDataFromTable:kChatMessageListTable andCondition:condition];
    NSNumber *dotNum = @0;
    if ([dotArr count]>0) {
        YZMessageListModel *tempModel = dotArr[0];
        dotNum = tempModel.redHotNumber;
    } else {
        dotNum = @0;
    }
    
    return [NSNumber numberWithInteger:([dotNum intValue] + 1)];;
}

- (void)checkSendStatus:(NSTimer *)timer {
    NSDictionary *userInfo = [timer userInfo];
    YZMessageFrame *messageF = [userInfo objectForKey:@"msg"];
    uint64_t messageTime = messageF.model.message.messageTime;
    // 更新消息状态
    BOOL isSendOK = isSendSuccess;
    [self updateSendMessageStatus:isSendOK
                        timeStamp:messageTime];
    if (isSendSuccess) {
        // 发送成功
        [self messageSendSuccess:messageF];
        isSendSuccess = NO;
        [timer invalidate];
        timer = nil;
        
    } else {
        // 发送失败
        [self messageSendFailure:messageF];
        isSendSuccess = NO;
        [timer invalidate];
        timer = nil;
        [[NSThread currentThread] cancel];
    }
}

// 发送时间
- (void)sendMessageTime:(int64_t)time {
    ImMessage *im = [[ImMessage alloc] init];
    int64_t tempTime = [[YZChatUtils getTimeInterval2] integerValue];
    if (time == 0) {
        im.messageTime = tempTime ;
    } else {
         im.messageTime = tempTime ;
    }
    
    YZMessageFrame *msgF = [YZMessageHelper createMessageFrame:TypeSystem imMessage:im path:nil fileKey:nil isSender:YES rececivedSenderbySelf:NO senderAvatar:@"" receiverAvatar:@""];
    [self refreshTableByMessageFrame:msgF];
}

// 保存接收的消息
- (void)saveAcceptedMessage:(YZMessageFrame *)messageF {
    NSInteger temTimeInterval = [[YZChatUtils getTimeInterval2] integerValue];
    [[YZDBManager sharedManage] insertData:messageF.model.message.playLoad mediaType:messageF.model.message.mediaType sendTime:temTimeInterval filePath:messageF.model.mediaPath fileKey:messageF.model.message.fileKey isSender:NO status:1 table:kChatRecordTable senderAvatar:[YZChatPeer shared].receiverAvatar receiverAvatar:[YZUser sharedInstance].avatar];
    
}

// 发送时 更新消息列表
- (void)updateSendMessageList:(YZMessageFrame *)messageF {
    YZMessage *p = messageF.model.message;
    [self queryUserInfo:p];
}

// 接收时 更新消息列表
- (void)updateAcceptMessageList:(YZMessageFrame *)messageF {
    YZMessage *p = messageF.model.message;
    NSString *recStr = @"";
    if ([p.mediaType isEqualToString:@"image/*"]) {
        recStr = @"[图片]";
    } else if ([p.mediaType isEqualToString:@"text/plain"]) {
        recStr = [[NSString alloc] initWithData:p.playLoad encoding:NSUTF8StringEncoding];
    } else if ([p.mediaType isEqualToString:@"audio/aac"]) {
        recStr = @"[语音]";
    } else if ([p.mediaType isEqualToString:@"video/mp4"]) {
        recStr = @"[视频]";
    }
    
    YZMessageListModel *model = [YZMessageListModel new];
    model.name = p.sender;
    model.imageName = @"";
    model.showUserId = p.sender;
    model.message = recStr;
    model.time = p.messageTime;
    // 这里作为接收方
    model.receiver = p.receiver;
    
    NSString *setStr = [NSString stringWithFormat:@"lastContent = '%@'",model.message];
    NSString *condition = [NSString stringWithFormat:@"showUserid = '%@'",model.showUserId];
    
    BOOL updateRet = [[YZDBManager sharedManage] updateData:setStr table:kChatMessageListTable andCondition:condition];
    if (updateRet) {
        NSLog(@"更新消息成功");
    }
}

// 保存发送的消息
- (void)saveSentMesssage:(YZMessageFrame *)messageF {
    messageF.model.message.deliveryState = ICMessageDeliveryState_Delivered;
    [[YZDBManager sharedManage] insertData:messageF.model.message.playLoad mediaType:messageF.model.message.mediaType sendTime:messageF.model.message.messageTime filePath:messageF.model.mediaPath fileKey:messageF.model.message.fileKey isSender:YES status:1 table:kChatRecordTable senderAvatar:[YZUser sharedInstance].avatar receiverAvatar:[YZChatPeer shared].receiverAvatar];
}

// 更新发送消息状态
- (void)updateSendMessageStatus:(BOOL)sendSuccess
                      timeStamp:(uint64_t)timeStamp{
    int sendStatus = 0;
    if (sendSuccess) {
        sendStatus = 1;
    }
    
    NSString *setStr = [NSString stringWithFormat:@"sendStatus = %d",sendStatus];
    NSString *condition = [NSString stringWithFormat:@"sendTime = %lld",timeStamp];
    BOOL updateRet = [[YZDBManager sharedManage] updateData:setStr table:kChatRecordTable andCondition:condition];
    
    if (updateRet) {
        NSLog(@"更新消息发送状态成功");
    }
}


- (void)progressChange
{
    AVAudioRecorder *recorder = [[YZRecordManager shareManager] recorder] ;
    [recorder updateMeters];
    float power= [recorder averagePowerForChannel:0];//取得第一个通道的音频，注意音频强度范围时-160到0,声音越大power绝对值越小
    CGFloat progress = (1.0/160)*(power + 160);
    self.voiceHud.progress = progress;
}

- (void)chooseFromAlbum {
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
        
        self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        [self presentViewController:self.imagePicker animated:YES completion:nil];
        
    }
}

- (void)takePhoto {
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
        [self presentViewController:self.imagePicker animated:YES completion:nil];
    }
}

- (void)takeVideo {
    if (![[YZVideoManager shareManager] canRecordViedo]) {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"请在iPhone的“设置-隐私”选项中，允许访问你的摄像头和麦克风。" message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        [alert show];
    }
    
    [self.view insertSubview:self.videoView aboveSubview:self.view];
    UIView *videoLayerView = [self.videoView viewWithTag:1000];
    UIView *placeholderView = [self.videoView viewWithTag:1001];
    [[YZVideoManager shareManager] setVideoPreviewLayer:videoLayerView];
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(videoPreviewLayerWillAppear:) userInfo:placeholderView repeats:NO];
}

// 移除录视频时的占位图片
- (void)videoPreviewLayerWillAppear:(NSTimer *)timer
{
    UIView *placeholderView = (UIView *)[timer userInfo];
    [placeholderView removeFromSuperview];
}

- (void)chatVoiceTaped:(YZMessageFrame *)messageFrame
             voiceIcon:(UIImageView *)voiceIcon
               redView:(UIView *)redView
{
    YZRecordManager *recordManager = [YZRecordManager shareManager];
    recordManager.playDelegate = self;
    
    NSString *voicePath = [[YZRecordManager shareManager] changeAudioPath:messageFrame.model.mediaPath];
    
    if (messageFrame.model.message.status == 0){
        messageFrame.model.message.status = 1;
        redView.hidden = YES;
    }
    if (self.tempRecorderPath) {
        if ([self.tempRecorderPath isEqualToString:voicePath]) { // the same recoder
            self.tempRecorderPath = nil;
            [[YZRecordManager shareManager] stopPlayRecorder:voicePath];
            [voiceIcon stopAnimating];
            self.currentVoiceIcon = nil;
//            return;
        } else {
            [self.currentVoiceIcon stopAnimating];
            self.currentVoiceIcon = nil;
        }
    }
    [[YZRecordManager shareManager] startPlayRecorder:voicePath];
    [voiceIcon startAnimating];
    self.tempRecorderPath = voicePath;
    self.currentVoiceIcon = voiceIcon;
}

- (void)accpetMessage:(ImMessage *)p {
    // 刷新页面
    NSString *receiveType = @"";
    NSString *path = @"";
    __block NSString *fileKey = nil;
    
    int64_t timeInterval = [[YZChatUtils getTimeInterval2] integerValue];
    if (timeInterval - self.lastVisibleTime > 60 * 3 * 1000) {
        // 发送时间
        [self sendMessageTime:timeInterval];
        self.lastVisibleTime = timeInterval;
    }
    
    if ([p.mediaType isEqualToString:@"text/plain"]) {
//        [self sendMessageTime:0];
        
        receiveType = TypeText;
        YZMessageFrame *messageF = [YZMessageHelper createMessageFrame:receiveType imMessage:p path:path fileKey:nil isSender:NO rececivedSenderbySelf:NO senderAvatar:[YZChatPeer shared].receiverAvatar receiverAvatar:[YZUser sharedInstance].avatar];
        
        [self refreshTableByMessageFrame:messageF];
        
        // 给服务器发送ack,确认收到离线消息
        [[ClientSocket shareSocket] doAck:p.messageId];
        
        // 保存消息
        [self saveAcceptedMessage:messageF];
        
        // 接收时 更新消息列表
        [self updateAcceptMessageList:messageF];
        
    }
    else if ([p.mediaType isEqualToString:@"audio/aac"]) {
//        [self sendMessageTime:0];
        
        receiveType = TypeVoice;
        // 保存录音文件名
        [self saveReceviceAudio:p.payload];
        path = _tempRecorderPath;
        
        YZMessageFrame *messageF = [YZMessageHelper createMessageFrame:receiveType imMessage:p path:path fileKey:nil isSender:NO rececivedSenderbySelf:NO senderAvatar:[YZChatPeer shared].receiverAvatar receiverAvatar:[YZUser sharedInstance].avatar];
        
        [self refreshTableByMessageFrame:messageF];
        
        // 给服务器发送ack,确认收到离线消息
        [[ClientSocket shareSocket] doAck:p.messageId];
        
        // 保存消息
        [self saveAcceptedMessage:messageF];
        
        // 接收时 更新消息列表
        [self updateAcceptMessageList:messageF];
    } else if ([p.mediaType isEqualToString:@"image/*"]) {
//        [self sendMessageTime:0];
        
        receiveType = TypePic;
        // 保存图片
        UIImage *thumbnailImage = [UIImage imageWithData:p.payload];
        
        UIImage *simpleImage = [UIImage simpleImage:thumbnailImage];
        
        path = [[YZMediaManager shareManager] saveImage:simpleImage];
        
        // 原图的Url
        NSString *orginImagUrlStr = p.mediaLink;
        
        [[YZImageManager shareManager] requestWithUrlStr:orginImagUrlStr
                                                   mediaType:p.mediaType
                                                   block:^(NSString *str) {
            fileKey = str;
            
            YZMessageFrame *messageF = [YZMessageHelper createMessageFrame:receiveType imMessage:p path:fileKey fileKey:fileKey isSender:NO rececivedSenderbySelf:NO senderAvatar:[YZChatPeer shared].receiverAvatar receiverAvatar:[YZUser sharedInstance].avatar];
            
            [self refreshTableByMessageFrame:messageF];
            
            // 给服务器发送ack,确认收到离线消息
            [[ClientSocket shareSocket] doAck:p.messageId];
            
            // 保存消息
            [self saveAcceptedMessage:messageF];
        
            // 接收时 更新消息列表
            [self updateAcceptMessageList:messageF];
                                                       
                                                       
                                                       
        }];
        
        
    } else if ([p.mediaType isEqualToString:@"video/mp4"]) {
//        [self sendMessageTime:0];
        
        receiveType = TypeVideo;
        // 保存视频的缩略图
        UIImage *thumbnailImage = [UIImage imageWithData:p.payload];
        UIImage *simpleImage = [UIImage simpleImage:thumbnailImage];
        
        // 视频缩略图地址
        NSString *fileName = [NSString stringWithFormat:@"%@%@",[NSString currentName],@".png"];
        NSString *videoImage =  [[YZMediaManager shareManager] saveVideoImage:thumbnailImage fileName:fileName];
        
        // 原视频的Url
        NSString *orginImagUrlStr = p.mediaLink;
        
        [[YZImageManager shareManager] requestWithUrlStr:orginImagUrlStr
                                               mediaType:p.mediaType
                                                   block:^(NSString *str) {
            fileKey = str;
            
            YZMessageFrame *messageF = [YZMessageHelper createMessageFrame:receiveType imMessage:p path:fileKey fileKey:videoImage isSender:NO rececivedSenderbySelf:NO senderAvatar:[YZChatPeer shared].receiverAvatar receiverAvatar:[YZUser sharedInstance].avatar];
            
            [self refreshTableByMessageFrame:messageF];
            
            // 给服务器发送ack,确认收到离线消息
            [[ClientSocket shareSocket] doAck:p.messageId];
                                                       
           // 保存消息
           [self saveAcceptedMessage:messageF];
                                                       
           // 接收时 更新消息列表
           [self updateAcceptMessageList:messageF];
        }];
        
        
    }
    
}

- (void)saveReceviceAudio:(NSData * _Nonnull)recData {
    // 生成录音文件名
    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"YYYYMMddHHmmssSSS"];
    NSString *dateStr = [formatter stringFromDate:date];
    _recorderName = [NSString stringWithFormat:@"%@%@",dateStr,@".aac"];
    _tempRecorderPath = [NSString stringWithFormat:@"%@%@",self.audioRecoderSavePath,_recorderName];
    
    // 写入文件
    NSError *writeErr = nil;
    BOOL wirteRec  = [recData writeToFile:_tempRecorderPath atomically:YES];
    if (!wirteRec) {
        NSLog(@"writeErr--->%@",[writeErr description]);
    }
    NSLog(@"接收到音频文件成功");
}


- (NSString *)currentRecordFileName{
    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSince1970];
    NSString *fileName = [NSString stringWithFormat:@"%ld",(long)timeInterval];
    return fileName;
}

// 处理接收服务端返回心跳延迟的情况，心跳返回：100000
- (BOOL)isDelayHeartRecData:(NSString *)recStr{
    BOOL isDelay = NO;
    NSUInteger num = 0;
    NSUInteger len = recStr.length;
    num = [YZChatUtils cauculateTimer:recStr subStr:@"100000"];
    if (num > 0) {
        if (num * 6 == len) {
            isDelay = YES;
        }
    }
    
    return isDelay;
}

// tap image
- (void)showLargeImageWithPath:(NSString *)imgPath
                  withMessageF:(YZMessageFrame *)messageF
{
    UIImage *image = [[YZMediaManager shareManager] imageWithLocalPath:imgPath];
    if (image == nil) {
        NSLog(@"image is not existed");
        return;
    }
    YZPhotoBrower *photoVC = [[YZPhotoBrower alloc] initWithImage:image];
    self.presentImageView.image       = image;
    photoVC.transitioningDelegate     = self;
    photoVC.modalPresentationStyle    = UIModalPresentationCustom;
    [self presentViewController:photoVC animated:YES completion:nil];
}

#pragma mark -- ChatKeyBoardDataSource
- (NSArray<MoreItem *> *)chatKeyBoardMorePanelItems
{
    MoreItem *item2 = [MoreItem moreItemWithPicName:@"sharemore_pic" highLightPicName:nil itemName:@"图片"];
    MoreItem *item3 = [MoreItem moreItemWithPicName:@"sharemore_video" highLightPicName:nil itemName:@"拍照"];
    MoreItem *item4 = [MoreItem moreItemWithPicName:@"sharemore_video" highLightPicName:nil itemName:@"视频"];
    return @[item2, item3, item4];
}
- (NSArray<ChatToolBarItem *> *)chatKeyBoardToolbarItems
{
    ChatToolBarItem *item1 = [ChatToolBarItem barItemWithKind:kBarItemFace normal:@"face" high:@"face_HL" select:@"keyboard"];
    
    ChatToolBarItem *item2 = [ChatToolBarItem barItemWithKind:kBarItemVoice normal:@"voice" high:@"voice_HL" select:@"keyboard"];
    
    ChatToolBarItem *item3 = [ChatToolBarItem barItemWithKind:kBarItemMore normal:@"more_ios" high:@"more_ios_HL" select:nil];
    
    ChatToolBarItem *item4 = [ChatToolBarItem barItemWithKind:kBarItemSwitchBar normal:@"switchDown" high:nil select:nil];
    
    return @[item1, item2, item3, item4];
}

- (NSArray<FaceThemeModel *> *)chatKeyBoardFacePanelSubjectItems
{
    NSMutableArray *subjectArray = [NSMutableArray array];
    
    NSArray *sources = @[@"emoji"];
    
    for (int i = 0; i < sources.count; ++i)
    {
        NSString *plistName = sources[i];
        
        NSString *plistPath = [[NSBundle mainBundle] pathForResource:plistName ofType:@"plist"];
        NSArray *faceArr = [NSArray arrayWithContentsOfFile:plistPath];
        
        
        FaceThemeModel *themeM = [[FaceThemeModel alloc] init];
        themeM.themeStyle = FaceThemeStyleCustomEmoji;
        themeM.themeDecribe = [NSString stringWithFormat:@"f%d", i];
        
        NSMutableArray *modelsArr = [NSMutableArray array];
        
        for (int i = 0; i < faceArr.count; ++i) {
            NSDictionary *tempDic = faceArr[i];
            NSString *name = @"";
            NSString  *tempCode = [tempDic objectForKey:@"code"];
            name =  tempCode.emoji;
            
            FaceModel *fm = [[FaceModel alloc] init];
            fm.faceTitle = name;
            fm.faceIcon = @"";
            fm.code = tempCode;
            [modelsArr addObject:fm];
        }
        themeM.faceModels = modelsArr;
        
        [subjectArray addObject:themeM];
    }
    
    return subjectArray;
}

#pragma mark - ChatKeyBoardDelegate
- (void)voiceDidCancelRecording {
    [self timerInvalue];
    self.voiceHud.hidden = YES;
}

- (void)voiceDidStartRecording {
    [self timerInvalue];
    self.voiceHud.hidden = NO;
    [self timer];
}

- (void)voiceRecordSoShort
{
    [self timerInvalue];
    self.voiceHud.animationImages = nil;
    self.voiceHud.image = [UIImage imageNamed:@"voiceShort"];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.voiceHud.hidden = YES;
    });
}

- (void)chatKeyBoardSendText:(NSString *)text {
    NSLog(@"send is---------->%@",text);
    NSData *sendDt = [text dataUsingEncoding:NSUTF8StringEncoding];
    
    int64_t timeInterval = [[YZChatUtils getTimeInterval2] integerValue];
    if (timeInterval - self.lastVisibleTime > 60 * 3 * 1000) {
        // 发送时间
        [self sendMessageTime:timeInterval];
        self.lastVisibleTime = timeInterval;
    }
    
    // 创建消息体
    ImMessage *mess = [YZChatUtils createMessage:@"YZIMP"
                version:@"1.0"
                 userId:[YZChatPeer shared].sender
              userToken:[YZUser sharedInstance].token
              messageId:1 messageType:@"data"
            messageTime:timeInterval
               termType:@"iOS"
               receiver:[YZChatPeer shared].receiver
                 sender:[YZChatPeer shared].sender
          ctrlMessageId:0
              mediaType:@"text/plain"
               playload:sendDt];
    
    // 创建消息对象
    YZMessageFrame *messageF = [YZMessageHelper createMessageFrame:TypeText imMessage:mess path:nil fileKey:nil isSender:YES rececivedSenderbySelf:NO senderAvatar:[YZUser sharedInstance].avatar receiverAvatar:[YZChatPeer shared].receiverAvatar];
    [self.chatData addObject:messageF];
    
    // 开启新线程检查发送状态
    NSThread *newThread = [[NSThread alloc]initWithTarget:self selector:@selector(threadRun:) object:(@{@"type":@"text/plain",@"msg":messageF,@"dt":sendDt})];
    newThread.name = @"thread_check_send";
    [newThread start];
}

// 计时
- (void)threadRun:(NSDictionary *)passDic{
    NSString *mediaType = passDic[@"type"];
    NSData *dt = passDic[@"dt"];
    // 发送消息
    [self doSendMessage:dt mediaType:mediaType messageType:@"data"];
    
    YZMessageFrame *messageF = [passDic objectForKey:@"msg"];
    uint64_t messageTime = messageF.model.message.messageTime;
    
    // 1s之后检查发送状态
    dispatch_queue_t queue = dispatch_queue_create("sendqueue", DISPATCH_QUEUE_SERIAL);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
                                 (int64_t)(1 * NSEC_PER_SEC)), queue, ^{
        
        // 如果是重发则更新消息状态
        BOOL isSendOK = isSendSuccess;
        if ([passDic objectForKey:@"reSend"]) {
            [self updateSendMessageStatus:isSendOK timeStamp:messageTime];
        } else {
            // 非重发则保存数据
            [self saveSentMesssage:messageF];
            
            // 检查自己的消息列表有没有和接受者的聊天记录
            [self updateSendMessageList:messageF];
        }
        
        
        if (isSendSuccess) {
            // 发送成功
            [self messageSendSuccess:messageF];
            [self updateSendMessageStatus:isSendOK timeStamp:messageTime];
            isSendSuccess = NO;
            
        } else {
            NSTimer *tempTimer =  [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(checkSendStatus:) userInfo:passDic repeats:NO];
            [[NSRunLoop currentRunLoop] addTimer:tempTimer forMode:NSRunLoopCommonModes];
            [[NSRunLoop currentRunLoop] run];
        }
    });
}

- (void)chatKeyBoardDidStartRecording:(ChatKeyBoard *)chatKeyBoard {
    self.recordName = [self currentRecordFileName];
    [[YZRecordManager shareManager] startRecordWithFileName:self.recordName completion:^(NSError *error) {
        if (error) {
        } else {
            [self voiceDidStartRecording];
        }
    }];
}

- (void)chatKeyBoardDidCancelRecording:(ChatKeyBoard *)chatKeyBoard {
    
}
- (void)chatKeyBoardDidFinishRecoding:(ChatKeyBoard *)chatKeyBoard {
    __weak typeof(self) weakSelf = self;
    [[YZRecordManager shareManager] stopRecordCompletion:^(NSString *finish) {
        if ([finish isEqualToString:shortRecord]) {
            [self voiceRecordSoShort];
            [[YZRecordManager shareManager] removeCurrentRecordFile:weakSelf.recordName];
        } else {
            [self timerInvalue];
            self.voiceHud.hidden = YES;
            NSData *sendAudioData = [YZChatUtils dataFromPath:finish];
            dispatch_queue_t que = dispatch_queue_create("send_audio_yinzi", DISPATCH_QUEUE_SERIAL);
            dispatch_async(que, ^{
                int64_t timeInterval = [[YZChatUtils getTimeInterval2] integerValue];
                if (timeInterval - self.lastVisibleTime > 60 * 3 * 1000) {
                    // 发送时间
                    [self sendMessageTime:timeInterval];
                    self.lastVisibleTime = timeInterval;
                }
                
                // 创建消息体
                ImMessage *mess = [YZChatUtils createMessage:@"YZIMP"
                                              version:@"1.0"
                                               userId:[YZChatPeer shared].sender
                                            userToken:[YZUser sharedInstance].token
                                            messageId:1 messageType:@"data"
                                          messageTime:timeInterval
                                             termType:@"iOS"
                                             receiver:[YZChatPeer shared].receiver
                                               sender:[YZChatPeer shared].sender
                                        ctrlMessageId:0
                                            mediaType:@"audio/aac"
                                             playload:sendAudioData];
                
                
                
                // 创建消息对象
                YZMessageFrame *messageF = [YZMessageHelper createMessageFrame:TypeVoice imMessage:mess path:finish fileKey:nil isSender:YES rececivedSenderbySelf:NO senderAvatar:[YZUser sharedInstance].avatar receiverAvatar:[YZChatPeer shared].receiverAvatar];
                [self.chatData addObject:messageF];
                
                // 开启新线程检查发送状态
                NSThread *newThread = [[NSThread alloc]initWithTarget:self selector:@selector(threadRun:) object:(@{@"type":@"audio/aac",@"msg":messageF,@"dt":sendAudioData})];
                newThread.name = @"thread_check_send";
                [newThread start];
                
            });
        }
    }];
}


/**
 *  更多功能
 */
- (void)chatKeyBoard:(ChatKeyBoard *)chatKeyBoard didSelectMorePanelItemIndex:(NSInteger)index {
    NSLog(@"点击了index------>%ld",index);
    switch (index) {
        case 0:
            // 相册
            [self chooseFromAlbum];
            break;
        case 1:
            // 拍照
            [self takePhoto];
            break;
        case 2:
            // 拍摄
            [self takeVideo];
            break;
        default:
            break;
    }
    
}

#pragma mark - YZRecordManagerDelegate
- (void)voiceDidPlayFinished
{
    self.tempRecorderPath = nil;
    YZRecordManager *manager = [YZRecordManager shareManager];
    manager.playDelegate = nil;
    [self.currentVoiceIcon stopAnimating];
    self.currentVoiceIcon = nil;
}

#pragma mark - longPressDelegate
- (void)longPress:(UILongPressGestureRecognizer *)longRecognizer {
    
}

- (void)headImageClicked:(NSString *)eId {
    
}

- (void)reSendMessage:(YZChatMessageBaseCell *)cell {
    NSLog(@"重发消息");
    NSString *messType = cell.modelFrame.model.message.type;
    NSData *sendDt= cell.modelFrame.model.message.playLoad;
    
    NSMutableDictionary *threadDic = [NSMutableDictionary dictionary];
    [threadDic setObject:cell.modelFrame forKey:@"msg"];
    [threadDic setObject:sendDt forKey:@"dt"];
    // 重发增加一个重发的标记
    [threadDic setObject:@"reSend" forKey:@"reSend"];
    
    NSString *messageType = @"";
    if ([messType isEqualToString:TypeText]) {
        messageType = @"text/plain";
    } else if ([messType isEqualToString:TypePic]) {
        messageType = @"image/*";
    } else if ([messType isEqualToString:TypeVoice]) {
        messageType = @"audio/aac";
    } else if ([messType isEqualToString:TypeVideo]) {
        messageType = @"video/mp4";
    }
    [threadDic setObject:messageType forKey:@"type"];
    
    NSThread *newThread = [[NSThread alloc]initWithTarget:self selector:@selector(threadRun:) object:threadDic];
    [newThread start];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
